﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections.ObjectModel;

namespace A3C_desktop
{
	/// <summary>
	/// MainWindow.xaml 的交互逻辑
	/// </summary>
	public partial class MainWindow : Window
	{
		public delegate void outputDel(string s);
		public delegate void UpdateRightStatusDel(int a, int b);
		public delegate void UpdateRunListViewDel();
		public int interval = 1000;
		private Thread capTh;
		private Thread updateUITh;
		private Timer thTimer;
		private int selAdp;
		private ObservableCollection<CapInfo> capInfoColl;
		private int pktCnt;
		private int proCnt;

		public MainWindow()
		{
			InitializeComponent();

			InitProcess();

		}

		private void InitProcess()
		{
			CppDll.Init();
			List<CategoryInfo> adpList = new List<CategoryInfo>();
			capInfoColl = new ObservableCollection<CapInfo>();
			runListView.ItemsSource = capInfoColl;

			int cnt = CppDll.GetAdapterCnt();
			int i = 0;
			while (i < cnt)
			{
				IntPtr p = CppDll.GetAdapterItem(i);
				string s = Marshal.PtrToStringUni(p);
				adpList.Add(new CategoryInfo { Name = s, Value = i.ToString() });
				i++;
			}
			this.AdapterList.ItemsSource = adpList;
			this.AdapterList.DisplayMemberPath = "Name";//显示出来的值
			this.AdapterList.SelectedValuePath = "Value";//实际选中后获取的结果的值
			selAdp = CppDll.SelectAdapter();
			AdapterList.SelectedIndex = selAdp;
		}

		private void Button_Click(object sender, RoutedEventArgs e)  //开始按钮
		{
			capTh = new Thread(StartCaptureFun);
			updateUITh = new Thread(UpdateUI);
			capTh.IsBackground = true;
			updateUITh.IsBackground = true;
			selAdp = AdapterList.SelectedIndex;
			capTh.Start(selAdp);
			Thread.Sleep(500);
			updateUITh.Start();
			StartBtn.IsEnabled = false;
			StopBtn.IsEnabled = true;
			runStatus.Text = "正在抓包...";
		}

		public void StartCaptureFun(object obj)
		{
			int adapterIndex = Convert.ToInt32(obj);
			//CppDll.StrDelCallBack = OutputLog;	//防止GC回收
			//CppDll.SetPInvoke(CppDll.StrDelCallBack);
			CppDll.StartCapture(adapterIndex);
		}

		public void UpdateUI()
		{
			thTimer = new Timer(new TimerCallback(TimerUp), null, Timeout.Infinite, 1000);  //注册计时器
			thTimer.Change(0, interval);
		}

		public void TimerUp(object value)	//到点执行的函数
		{
			//int pktCnt = CppDll.GetPktCnt();
			//int proCnt = CppDll.GetProCnt();
			runListView.Dispatcher.Invoke(new UpdateRunListViewDel(UpdateRunListViewAction));
			captureStatus.Dispatcher.Invoke(new UpdateRightStatusDel(UpdateRightStatusAction), proCnt, pktCnt);
		}

		public void UpdateRightStatusAction(int proCnt, int pktCnt)
		{
			captureStatus.Text = "进程：" + proCnt + ", 包数量：" + pktCnt;
		}

		public void UpdateRunListViewAction()
		{
			pktCnt = 0;
			proCnt = 0;
			capInfoColl.Clear();
			IntPtr PproName = Marshal.AllocHGlobal(2560);
			IntPtr Pcnt = Marshal.AllocHGlobal(sizeof(int));

			int index = 0;
			int res = CppDll.GetCapInfo(index, PproName, Pcnt);

			while (res >= 0)
			{
				string proName = Marshal.PtrToStringAnsi(PproName);
				int cnt = Marshal.ReadInt32(Pcnt);
				capInfoColl.Add(new CapInfo(proName, cnt));
				index++;
				pktCnt += cnt;
				proCnt += 1;
				res = CppDll.GetCapInfo(index, PproName, Pcnt);
			}
			Marshal.FreeHGlobal(PproName);
			Marshal.FreeHGlobal(Pcnt);
		}
		//public void OutputLog(string s)
		//{
		//	RunLog.Dispatcher.Invoke(new outputDel(OutputLogAction), s);
		//}

		//private void OutputLogAction(string s)
		//{
		//	//RunLog.AppendText(s);
		//	RunLog.Text = s;
		//	//MessageBox.Show(s);
		//}

		private void Button_Click_1(object sender, RoutedEventArgs e)  //结束按钮
		{
			runStatus.Text = "正在结束，请稍候...";
			//MessageBox.Show("正在结束");
			Thread.Sleep(100);
			CppDll.BreakLoop();
			capTh.Join();
			thTimer.Change(Timeout.Infinite, interval);
			CppDll.CleanUp();
			StartBtn.IsEnabled = true;
			StopBtn.IsEnabled = false;
			runStatus.Text = "";
			IntPtr p = CppDll.GetOutputDir();
			string path = Marshal.PtrToStringAnsi(p);
			System.Diagnostics.Process.Start(path);
		}
	}

	public class CategoryInfo
	{
		public string Name { get; set; }
		public string Value { get; set; }
	}

	public class CapInfo
	{
		public string ProName { get; set; }
		public int PktCnt { get; set; }
		public CapInfo(string s, int i)
		{
			ProName = s;
			PktCnt = i;
		}
	}

	public class CppDll
	{
		//const string DllPath = "C:\\WSpace\\A3C_2\\Debug\\A3C_2.dll";
		const string DllPath = "A3C_2.dll";
		//public delegate void StrDel(string s);
		//public static StrDel StrDelCallBack;	//防止GC回收

		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static int Init();
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static IntPtr GetAdapterItem(int i);
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static int StartCapture(int index);
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static int GetAdapterCnt();
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static int BreakLoop();
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static int CleanUp();
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static int SelectAdapter();
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static IntPtr GetOutputDir();
		//[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		//public extern static void SetPInvoke(StrDel fun);
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static int GetPktCnt();
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static int GetProCnt();
		[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl)]
		public extern static int GetCapInfo(int index, IntPtr proName, IntPtr cnt);
	}
}
